package daoImpl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Date;

import org.apache.log4j.Logger;

import queries.QueriesContrato;

import constants.Constants;
import dao.ApartamentoDAO;
import dao.ContratoDAO;

import util.Helper;
import entities.Apartamento;
import entities.Contrato;
import exceptions.DataInvalidaException;
import exceptions.MensalidadeExistenteException;


/**
 * @author tiago.de.l.wanderley
 * @since 03/05/2010
 */
public class ContratoDAOImpl implements ContratoDAO{

	private static Logger log = Logger.getLogger(ContratoDAOImpl.class);

	private static ContratoDAOImpl contratoDAOImpl = null;

	public static ContratoDAOImpl getInstance(){
		if(contratoDAOImpl == null){
			contratoDAOImpl = new ContratoDAOImpl();
		}
		return contratoDAOImpl;
	}

	@Override
	public void cadastrarContrato(String dataInicioContrato,
			String cpfLocatario, String cpfFiador, Apartamento apto, int tempoContrato, Connection connection)
	throws SQLException, ParseException, DataInvalidaException {

		log.debug("Inicio do metodo DAOImpl.cadastrarContrato.");

		log.debug("Cadastrando o contrato com o seguintes dados: " + Constants.LINE_SEPARATOR +
				"Data Inicio do contrato: " + dataInicioContrato + Constants.LINE_SEPARATOR +
				"cpf do Locatario: " + cpfLocatario + Constants.LINE_SEPARATOR +
				"cpf do Fiador: " + cpfFiador + Constants.LINE_SEPARATOR + "\n" +
				"Numero do Apto: " + apto.getNumero() + Constants.LINE_SEPARATOR +
				"Bloco do Apartamento: " + apto.getBloco() + Constants.LINE_SEPARATOR +
				"Tempo de Contrato: " + tempoContrato);

			PreparedStatement pstm = connection.prepareStatement(Queries.CADASTRAR_CONTRATO);

			pstm.setDate(1,new java.sql.Date(Helper.getStringAsSimpleDate(
					dataInicioContrato).getTime()));

			pstm.setDate(2, new java.sql.Date(Helper.incrementaMes(dataInicioContrato, tempoContrato).getTime()));
			pstm.setString(3, cpfLocatario);
			pstm.setString(4, cpfFiador);
			pstm.setString(5, apto.getNumero());
			pstm.setString(6, apto.getBloco());
			pstm.setDate(7,new java.sql.Date(Helper.getStringAsSimpleDate(
					dataInicioContrato).getTime()));
			pstm.setInt(8, Helper.getDiaInt(dataInicioContrato));
			pstm.executeUpdate();
	}

	/**
	 * @throws SQLException
	 * @throws ParseException
	 * @throws MensalidadeExistenteException
	 * @see dao.ContratoDAO#renovarContrato(java.lang.String, java.lang.String, java.sql.Connection)
	 */
	@Override
	public void renovarContrato(Contrato contrato, int tempoContrato, Connection connection, ApartamentoDAO apartamentoDAO) throws SQLException, ParseException, MensalidadeExistenteException {

		log.debug("Inicio do metodo ContratoDAOImpl.renovarContrato.");

		log.debug("Renovando o contrato:\n" + contrato +
				"\nTempo de contrato: " + tempoContrato);

		PreparedStatement pstm = connection.prepareStatement(QueriesContrato.RENOVAR_CONTRATO);

		pstm.setDate(1, new java.sql.Date(Helper.incrementaMes(Helper.getDateAsFormattedString(contrato.getDataFim()), tempoContrato).getTime()));
		pstm.setDate(2, new java.sql.Date(Helper.getDateAsSimpleDate(new Date()).getTime()));
		pstm.setString(3,contrato.getCpfFiador());
		pstm.setString(4,contrato.getCpfLocatario());
		pstm.executeUpdate();

		for (int i = 1; i <= tempoContrato; i++) {
			Date vencimento = Helper.incrementaMes(Helper.getDateAsFormattedString(contrato.getDataFim()), i);
			apartamentoDAO.cadastraMensalidade(contrato.getApto(), vencimento, true, true ,false, false, connection);
		}
	}

	/**
	 * @throws SQLException
	 * @see dao.ContratoDAO#cancelarContrato(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.sql.Connection)
	 */
	@Override
	public void excluirContrato(Contrato contrato, Connection connection) throws SQLException {

		log.debug("Inicio do metodo ContratoDAOImpl.cancelarContrato.");

		log.debug("Cancelando o contrato:" + contrato);

		PreparedStatement pstm = connection.prepareStatement(QueriesContrato.EXCLUIR_CONTRATO);
		pstm.setString(1, contrato.getCpfLocatario());
		pstm.setString(2, contrato.getCpfFiador());
		pstm.executeUpdate();
		pstm.close();
	}

	@Override
	public Contrato recuperarContrato(Apartamento apto, Connection connection) throws SQLException{
		log.debug("Inicio do metodo ContratoDAOImpl.canrecuperarContratocelarContrato.");

		log.debug("Recuperando o contrato:" +
				"\nnumero do apartamento: " + apto.getNumero() +
				"\nbloco: " + apto.getBloco());

		PreparedStatement pstm = connection.prepareStatement(QueriesContrato.RECUPERA_CONTRATO);
		pstm.setString(1, apto.getNumero());
		pstm.setString(2, apto.getBloco());
		ResultSet rs = pstm.executeQuery();
		Contrato contrato = new Contrato();

		if(rs.next()){
			contrato.setApto(apto);
			contrato.setDataFim(new java.util.Date(rs.getDate("dataFim").getTime()));
			contrato.setDataInicio(new java.util.Date(rs.getDate("dataInicio").getTime()));
			contrato.setCpfFiador(rs.getString("cpfFiador"));
			contrato.setCpfLocatario(rs.getString("cpfLocatario"));
			contrato.setBloco(apto.getBloco());
			contrato.setNumero(apto.getNumero());
			contrato.setDataRenovacao(new java.util.Date(rs.getDate("DATA_RENOVACAO").getTime()));
			contrato.setDiaVencimento(rs.getString("DIA_VENCIMENTO"));
		}

		rs.close();
		pstm.close();

		return contrato;
	}

	@Override
	public void atualizaContrato(Contrato contrato, Connection connection)
			throws SQLException{

			log.debug("Inicio do metodo ContratoDAOImpl.atualizaContrato.");

			log.debug("renovando o contrato:" + contrato);

			PreparedStatement pstm = connection.prepareStatement(QueriesContrato.ATUALIZA_CONTRATO);
			pstm.setString(1, contrato.getNumero());
			pstm.setString(2, contrato.getBloco());
			pstm.setString(3, contrato.getDiaVencimento());
			pstm.setString(4, contrato.getCpfFiador());
			pstm.setString(5, contrato.getCpfLocatario());
			pstm.executeUpdate();
			pstm.close();
		}

}
